﻿/*
 * @author: wizardc
 */

using Dou.Job;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Jobs;
using UnityEngine;

namespace Demo.WorldMap.Prefab
{
    /// <summary>
    /// Prefab 类型渲染类，渲染一颗 BVH 树
    /// </summary>
    public unsafe class SceneStaticPrefabRender : ISceneStaticRender
    {
        public Transform parent;
        public PrefabStaticRenderRes[] res;
        public PrefabStaticRenderTree tree;
        
        public SceneStaticCameraCtl cameraCtl;
        
        private PrefabResContainer _container;
        
        private NativeArray<bool> _visibleFlagArray; // 节点显示状态数组
        
        private NodeVisibleUpdateJob _nodeManagedJob;
        private ManagedJob<NodeVisibleUpdateJob> _nodeJob;
        private JobHandle _nodeJobHandle;
        
        private ulong _renderNodeHandler;

        private bool _needLateUpdate = false;

        private bool _enable = true;
        
        public void SetEnable(bool enable)
        {
            _enable = enable;
            if (_container != null)
            {
                _container.SetEnable(_enable);
            }
        }

        // 预制 LOD 走内置的实现，这里的接口不做任何处理
        public void SetLOD(int lod)
        {
        }

        // 预制不接入强制刷新的逻辑
        public void SetForceUpdate()
        {
        }

        public void OnEnable()
        {
            _container = new PrefabResContainer();
            _container.Init(parent, res, tree);
            _container.SetEnable(_enable);
            
            _visibleFlagArray = new NativeArray<bool>(tree.nodes.Length, Allocator.Persistent);
            
            _nodeManagedJob = new NodeVisibleUpdateJob
            {
                cameraCtl = cameraCtl,
                container = _container,
                visibleFlagArray = _visibleFlagArray
            };
            _nodeJob = new ManagedJob<NodeVisibleUpdateJob>();
            _nodeJob.Work = _nodeManagedJob;
        }
        
        public void Update()
        {
            if (!_enable)
            {
                return;
            }
            _needLateUpdate = true;
            
            var nodePtr = (PrefabStaticRenderNode*) UnsafeUtility.PinGCArrayAndGetDataAddress(tree.nodes, out _renderNodeHandler);
            
            _nodeManagedJob.nodePtr = nodePtr;
            _nodeJobHandle = _nodeJob.Schedule();
            JobHandle.ScheduleBatchedJobs();
        }

        public void LateUpdate()
        {
            if (!_needLateUpdate)
            {
                return;
            }
            _needLateUpdate = false;
            
            _nodeJobHandle.Complete();
            
            UnsafeUtility.ReleaseGCObject(_renderNodeHandler);
            
            _container.Update();
        }

        public void OnDisable()
        {
            _visibleFlagArray.Dispose();
            _nodeManagedJob = null;
            _nodeJob.Dispose();
            _container.Dispose();
        }

#if UNITY_EDITOR

        public void DrawObjAABB()
        {
            _container.DrawObjAABB();
        }
        
#endif

    }
}
